package core;

import java.io.*;
import javax.microedition.io.*;
import utils.Utils;

public class Connection implements Runnable{
	private SocketConnection sc;
	private InputStream dis;
	private OutputStream dos;
	private Thread thread;
	private Action listener;
	private String ip;
	private byte[] loginData;
	private boolean z;//флаг основного цыкла
	private boolean login;//если нужно залогинивание
	private boolean notDisconnection;
	private boolean _isOpen;
	
	public Connection(String ip,byte[] loginData,Action a)
	{
		sc = null;
		this.ip = ip; 
		listener = a;
		notDisconnection = true;
		login = true;
		_isOpen = false;
		this.loginData = loginData;
		start();
	}
	
	private void start()//Функция запуска потока
	{
		thread = new Thread(this);
		z = true;
		thread.start();
	}

	private void stop()//Функция остоновки потока
	{
		z = false;
	}
	
	public void run()//Основной цикл потока
	{
		while(z)
		{
			if (sc==null)
			{
				try
				{
					sc = (SocketConnection)Connector.open("socket://"+ip,Connector.READ_WRITE,true);
                                        try
                                        {
                                            sc.setSocketOption(SocketConnection.KEEPALIVE, 1);
                                        }catch(Exception e){}
                                        dis = sc.openInputStream();
					dos = sc.openOutputStream();
					_isOpen = true;
				}catch(IOException ioe)
				{
                                    //System.out.println("ERR: " + ioe.getMessage());
                                    //MainOne.LOG_STR += ("ERR: " + ioe.getMessage());

					if (notDisconnection)
					{
						String errorString;
						errorString = "txt_connectionerror";
						try
						{
							listener.action(0,errorString.getBytes("utf8"));
						}catch(Exception e)
						{
							listener.action(0,errorString.getBytes());
						}
						_isOpen = false;
						return;
					}
				}
				catch(SecurityException se)
				{
					String errorString;
					errorString = "txt_accesserror";
					try
					{
						listener.action(0,errorString.getBytes("utf8"));
					}catch(Exception e)
					{
						listener.action(0,errorString.getBytes());
					}
					_isOpen = false;
					return;
				}
				catch(Exception e){/*System.out.println("ERR: " + e.getMessage());/*MainOne.LOG_STR += ("ERR: " + e.getMessage());*/}
			}
			if (login)
			{
				try
				{
					send(loginData);
					login = false;
				}
				catch(Exception e)
				{
                                    //System.out.println("ERR: " + e.getMessage());
					String errorString;
					errorString = "txt_loginerror";
					try
					{
						listener.action(0,errorString.getBytes("utf8"));
					}catch(Exception err)
					{
						listener.action(0,errorString.getBytes());
					}
					_isOpen = false;
					return;
				}
			}
			try
			{
				byte[] sizebuff;
				sizebuff = new byte[4];
				for (int i=0;i<4;i++)
				{
					sizebuff[i] = (byte)dis.read();
				}
				//Пропускаем 4 байта - версия протокола
				for (int i=0;i<4;i++)
				{
					dis.read();
				}
				int size = Utils.byteToInt(sizebuff);
				byte[] buff;
				buff = new byte[size];
                                
				//new code
                                //-------------------------------------------------------------------- 
                                int read = dis.read(buff, 0, size);
                                int reread = read;
                                while (read < size /*&& dis.available() > 0*/ && reread != -1)   
                                {
                                    reread = dis.read(buff,read, size - read);
                                    if (read == -1) {
                                        break;
                                    }
                                    read += reread;
                                }
                                
                                //Если не все прочитали
                                if (read != size) {
                                    throw new IOException("read not all data");
                                }
                                
                                //=====================================================================
                                
                                //old code
                                //-------------------------------------------------------------------- 
//                                for (int i=0;i<size;i++)
//				{
//					buff[i] = (byte)dis.read();
//				}
                                //=====================================================================                         

                                listener.action(1,buff);
			}
			catch(IOException ioe)
			{
                            //MainOne.LOG_STR += ("ERR: " + ioe.getMessage());

				if (notDisconnection)
				{
					String errorString;
					errorString = "txt_connectionerror";
					try
					{
						listener.action(0,errorString.getBytes("utf8"));
					}catch(Exception e)
					{
						listener.action(0,errorString.getBytes());
					}
					return;
				}
			}
			catch(Exception e){/*MainOne.LOG_STR += ("ERR: " + e.getMessage());*/}
		}
	}
	
	public boolean send(byte[] buff)//Функция отправки данных по сети
	{
		try
		{
			if (dos!=null)//Если исходяший поток созданн,то отправляем данные
			{
				dos.write(buff);
				dos.flush();
				return true;
			}
			else//Если не создан - возвращаем false
			{
				return false;
			}
		}
		catch(IOException ioe)
		{
			return false;
		}
	}
	
	public void sendLogout(byte[] buff)
	{
		try
		{
			if (dos!=null)//Если исходяший поток созданн,то отправляем данные
			{
				dos.write(buff);
			}
			disconnect();
			listener.action(2,null);
		}
		catch(Exception e)
		{
			listener.action(2,null);
		}
	}

	public void disconnect()//Функция разрыва соединения
	{
		try
		{
			_isOpen = false;
			notDisconnection = false;
			stop();
			dos.close();
			dis.close();
			sc.close();
                        sc = null;
			thread = null;
			System.gc();
		}catch(Exception e){System.out.println("Exception in disc");}
	}
	
	public boolean isOpen()
	{
		return _isOpen;
	}
}